import {
  SubscribeMessage,
  WebSocketGateway,
  WebSocketServer,
} from "@nestjs/websockets";
import { Server } from "socket.io";
import { VedioService } from "./vedio.service";

const roomKey = "meeting-room::";
const userMap = new Map(); // user - > socket

/**
 * 统一返回参数
 */
function getMsg(type, msg, status = 200, data = null) {
  return { type: type, msg: msg, status: status, data: data };
}

/**
 * ono to one
 * @author suke
 * @param {Object} uid
 * @param {Object} msg
 */
function oneToOne(uid, msg) {
  let s = userMap.get(uid);
  if (s) {
    s.emit("msg", msg);
  } else {
    console.log(uid + "用户不在线");
  }
}

/**
 * 获取房间用户列表(k-v) 原始KV数据
 * @author masaikk
 * @param {Object} roomId
 */
async function getRoomUser(roomId) {
  return await VedioService.prototype.hGetAll(roomKey + roomId);
}

/**
 * broadcast
 * @author masaikk
 * @param {Object} roomId
 * @param {Object} msg
 */
async function oneToRoomMany(roomId, msg) {
  let uMap = await getRoomUser(roomId);
  for (const uid in uMap as Array<any>) {
    oneToOne(uid, msg);
  }
}

/**
 * 获取房间用户列表(list)
 * @author masaikk
 * @param {Object} roomId
 */
async function getRoomOnlyUserList(roomId) {
  let resList = [];
  let uMap = await VedioService.prototype.hGetAll(roomKey + roomId);
  for (const key in uMap as Array<any>) {
    let detail = JSON.parse(uMap[key]);
    resList.push(detail);
  }
  return resList;
}

@WebSocketGateway({
  path: "/socket", // 路径
  cors: {
    origin: "*", // 允许跨域
  },
})
export class VedioGateway {
  constructor(private readonly vedioService: VedioService) {}

  @WebSocketServer()
  server: Server; // socket实例
  onlineCount: number = 0; // 在线人数
  users: any = {}; // 用户列表
  // 监听客户端连接事件
  handleConnection(client): string {
    return "connect success";
  }

  // 监听客户端断开连接事件
  handleDisconnect(client) {}

  // 监听客户端的join事件
  @SubscribeMessage("join")
  handleJoin(client, userId: any): string {
    return "join success";
  }

  @SubscribeMessage("msg")
  async handleMsg(roomId: number, data: any) {
    console.log("msg", data);
    await oneToRoomMany(roomId, data);
  }

  @SubscribeMessage("roomUserList")
  async handleUserList(data: any) {
    this.server.emit("roomUserList", await getRoomOnlyUserList(data["roomId"]));
  }

  @SubscribeMessage("call")
  async handleCall(data: any) {
    let targetUid = data["targetUid"];
    oneToOne(targetUid, getMsg("call", "远程呼叫", 200, data));
  }

  @SubscribeMessage("offer")
  async handleOffer(data: any) {
    let targetUid = data["targetUid"];
    oneToOne(targetUid, getMsg("offer", "rtc offer", 200, data));
  }

  @SubscribeMessage("candidate")
  async handleCandidate(data: any) {
    let targetUid = data["targetUid"];
    oneToOne(targetUid, getMsg("candidate", "ice candidate", 200, data));
  }

  @SubscribeMessage("answer")
  async handleAnswer(data: any) {
    let targetUid = data["targetUid"];
    oneToOne(targetUid, getMsg("answer", "rtc answer", 200, data));
  }
}
